{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pandas sort_index() - 按索引排序详解\n\n本教程详细介绍如何使用 `sort_index()` 方法对 DataFrame 和 Series 按索引进行排序。\n\n## 目录\n1. sort_index() 基础用法\n2. 行索引排序\n3. 列索引排序\n4. 多级索引排序\n5. 排序参数详解\n6. 实际应用场景"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 导入库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\nimport numpy as np\nimport warnings\nwarnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. sort_index() 基础用法\n\n### 方法说明\n\n`sort_index()` 用于按照索引（行索引或列索引）对 DataFrame 或 Series 进行排序。\n\n**语法:**\n```python\ndf.sort_index(axis=0, level=None, ascending=True, inplace=False,\n              kind='quicksort', na_position='last', sort_remaining=True,\n              ignore_index=False, key=None)\n```\n\n**主要参数:**\n- `axis`: 0(按行索引排序) 或 1(按列索引排序)，默认 0\n- `ascending`: True(升序) 或 False(降序)，默认 True\n- `level`: 多级索引时指定排序的级别\n- `inplace`: 是否直接修改原 DataFrame，默认 False\n- `na_position`: 缺失值位置，'first' 或 'last'，默认 'last'\n\n**特点:**\n- ✅ 按索引标签排序，不是按值\n- ✅ 支持行索引和列索引排序\n- ✅ 支持多级索引排序\n- ✅ 默认返回新 DataFrame\n\n**适用场景:** 需要按索引顺序整理数据时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建示例数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建带有乱序索引的 DataFrame\ndf = pd.DataFrame({\n    '数学': [85, 92, 78, 96, 88],\n    '英语': [90, 85, 95, 82, 91],\n    '语文': [88, 90, 85, 94, 87]\n}, index=['张三', '李四', '王五', '赵六', '孙七'])\n\n# 重新排列索引顺序\ndf = df.reindex(['王五', '张三', '赵六', '李四', '孙七'])\n\nprint(\"原始数据（索引乱序）:\")\nprint(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 最简单的索引排序\n\n按行索引排序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sorted = df.sort_index()\nprint(\"按行索引排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 降序排序\n\n按行索引降序排序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sorted = df.sort_index(ascending=False)\nprint(\"按行索引降序排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 行索引排序\n\n详细介绍行索引排序的各种情况。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 数字索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建数字索引的 DataFrame\ndf_num = pd.DataFrame({\n    'A': [1, 2, 3, 4, 5],\n    'B': [10, 20, 30, 40, 50]\n}, index=[3, 1, 4, 2, 5])\n\nprint(\"数字索引（乱序）:\")\nprint(df_num)\n\ndf_sorted = df_num.sort_index()\nprint(\"\\n按数字索引排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 日期索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建日期索引\ndates = pd.to_datetime(['2023-03-15', '2023-01-10', '2023-05-20', '2023-02-08'])\ndf_date = pd.DataFrame({\n    '销售额': [1000, 1200, 800, 1500],\n    '订单数': [50, 60, 40, 75]\n}, index=dates)\n\nprint(\"日期索引（乱序）:\")\nprint(df_date)\n\ndf_sorted = df_date.sort_index()\nprint(\"\\n按日期索引排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: Series 索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建 Series\ns = pd.Series([10, 20, 30, 40], index=['d', 'b', 'a', 'c'])\nprint(\"原始 Series:\")\nprint(s)\n\ns_sorted = s.sort_index()\nprint(\"\\n按索引排序:\")\nprint(s_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 列索引排序\n\n按列名对列进行排序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 方法说明\n\n使用 `axis=1` 参数可以按列索引（列名）排序。\n\n**语法:**\n```python\ndf.sort_index(axis=1)\n```\n\n**特点:**\n- 按列名的字母顺序排序\n- 改变列的显示顺序\n- 不影响数据内容\n\n**适用场景:** 需要按列名顺序整理数据时"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 按列名排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建列名乱序的 DataFrame\ndf_cols = pd.DataFrame({\n    '语文': [88, 90, 85],\n    '数学': [85, 92, 78],\n    '英语': [90, 85, 95],\n    '物理': [82, 88, 90]\n}, index=['张三', '李四', '王五'])\n\nprint(\"原始数据（列名乱序）:\")\nprint(df_cols)\n\ndf_sorted = df_cols.sort_index(axis=1)\nprint(\"\\n按列名排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 列名降序排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sorted = df_cols.sort_index(axis=1, ascending=False)\nprint(\"按列名降序排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 同时排序行和列索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先按行索引排序，再按列索引排序\ndf_both = df_cols.reindex(['王五', '张三', '李四'])  # 重新排列行\nprint(\"行列都乱序的数据:\")\nprint(df_both)\n\n# 先排序行索引\ndf_sorted = df_both.sort_index()\nprint(\"\\n排序行索引:\")\nprint(df_sorted)\n\n# 再排序列索引\ndf_sorted = df_sorted.sort_index(axis=1)\nprint(\"\\n再排序列索引:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 多级索引排序\n\n处理 MultiIndex（多级索引）的排序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 方法说明\n\n多级索引排序可以指定排序的级别。\n\n**参数:**\n- `level`: 指定排序的级别（数字或名称）\n- `sort_remaining`: 是否对剩余级别排序\n\n**特点:**\n- 可以只对某一级别排序\n- 支持多级别同时排序\n- 保持层次结构\n\n**适用场景:** 处理分组数据或时间序列数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例1: 创建多级索引数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建多级行索引\narrays = [\n    ['A班', 'A班', 'B班', 'B班', 'C班', 'C班'],\n    ['张三', '李四', '王五', '赵六', '孙七', '周八']\n]\nindex = pd.MultiIndex.from_arrays(arrays, names=['班级', '姓名'])\n\ndf_multi = pd.DataFrame({\n    '数学': [85, 92, 78, 96, 88, 90],\n    '英语': [90, 85, 95, 82, 91, 87]\n}, index=index)\n\nprint(\"多级索引数据:\")\nprint(df_multi)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例2: 按第一级索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sorted = df_multi.sort_index(level=0)\nprint(\"按第一级索引（班级）排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例3: 按第二级索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sorted = df_multi.sort_index(level=1)\nprint(\"按第二级索引（姓名）排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例4: 按多个级别排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 先按班级，再按姓名排序\ndf_sorted = df_multi.sort_index(level=[0, 1])\nprint(\"按班级和姓名排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 示例5: 多级列索引排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建多级列索引\ncol_arrays = [\n    ['成绩', '成绩', '排名', '排名'],\n    ['数学', '英语', '数学', '英语']\n]\ncolumns = pd.MultiIndex.from_arrays(col_arrays, names=['类型', '科目'])\n\ndf_multi_col = pd.DataFrame(\n    [[85, 90, 1, 2], [92, 85, 2, 1], [78, 95, 3, 3]],\n    index=['张三', '李四', '王五'],\n    columns=columns\n)\n\nprint(\"多级列索引数据:\")\nprint(df_multi_col)\n\n# 按列索引排序\ndf_sorted = df_multi_col.sort_index(axis=1)\nprint(\"\\n按列索引排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. 排序参数详解\n\n详细说明 sort_index() 的各个参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数1: kind 参数\n\n指定排序算法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建测试数据\ndf_test = pd.DataFrame({\n    'A': [1, 2, 3, 4, 5]\n}, index=[5, 2, 8, 1, 3])\n\nprint(\"原始数据:\")\nprint(df_test)\n\n# 不同排序算法\nalgorithms = ['quicksort', 'mergesort', 'heapsort']\nfor alg in algorithms:\n    df_sorted = df_test.sort_index(kind=alg)\n    print(f\"\\n{alg} 排序:\")\n    print(df_sorted.index.tolist())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数2: na_position 参数\n\n处理索引中的缺失值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建包含 NaN 索引的数据\ndf_na = pd.DataFrame({\n    'A': [1, 2, 3, 4]\n}, index=[1.0, np.nan, 3.0, 2.0])\n\nprint(\"包含 NaN 索引的数据:\")\nprint(df_na)\n\n# 缺失值在最后（默认）\ndf_sorted = df_na.sort_index()\nprint(\"\\n缺失值在最后:\")\nprint(df_sorted)\n\n# 缺失值在最前\ndf_sorted = df_na.sort_index(na_position='first')\nprint(\"\\n缺失值在最前:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数3: key 参数\n\n自定义索引排序逻辑。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建字符串索引\ndf_str = pd.DataFrame({\n    'A': [1, 2, 3, 4]\n}, index=['item_10', 'item_2', 'item_1', 'item_20'])\n\nprint(\"字符串索引数据:\")\nprint(df_str)\n\n# 默认字符串排序\ndf_sorted = df_str.sort_index()\nprint(\"\\n默认字符串排序:\")\nprint(df_sorted)\n\n# 按数字部分排序\nimport re\ndef extract_number(x):\n    return x.str.extract(r'(\\d+)').astype(int).iloc[:, 0]\n\ndf_sorted = df_str.sort_index(key=extract_number)\nprint(\"\\n按数字部分排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 实际应用场景\n\nsort_index() 在实际数据分析中的应用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 场景1: 时间序列数据整理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建时间序列数据\ndates = pd.date_range('2023-01-01', periods=10, freq='D')\n# 随机打乱日期顺序\nshuffled_dates = dates[[3, 1, 7, 2, 9, 0, 5, 8, 4, 6]]\n\nts_data = pd.DataFrame({\n    '温度': np.random.randint(15, 30, 10),\n    '湿度': np.random.randint(40, 80, 10)\n}, index=shuffled_dates)\n\nprint(\"乱序的时间序列数据:\")\nprint(ts_data)\n\n# 按时间排序\nts_sorted = ts_data.sort_index()\nprint(\"\\n按时间排序:\")\nprint(ts_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 场景2: 分组数据整理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建分组数据\ndf_group = pd.DataFrame({\n    '销售额': [1000, 1200, 800, 1500, 900, 1100],\n    '利润': [200, 300, 150, 400, 180, 250]\n}, index=pd.MultiIndex.from_tuples([\n    ('北京', '产品A'), ('上海', '产品B'), ('北京', '产品B'),\n    ('广州', '产品A'), ('上海', '产品A'), ('广州', '产品B')\n], names=['城市', '产品']))\n\nprint(\"分组数据:\")\nprint(df_group)\n\n# 按城市和产品排序\ndf_sorted = df_group.sort_index()\nprint(\"\\n按城市和产品排序:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 场景3: 数据合并前的预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建两个需要合并的 DataFrame\ndf1 = pd.DataFrame({\n    '价格': [100, 200, 300]\n}, index=['产品C', '产品A', '产品B'])\n\ndf2 = pd.DataFrame({\n    '库存': [50, 30, 80]\n}, index=['产品B', '产品C', '产品A'])\n\nprint(\"DataFrame 1:\")\nprint(df1)\nprint(\"\\nDataFrame 2:\")\nprint(df2)\n\n# 排序后合并\ndf1_sorted = df1.sort_index()\ndf2_sorted = df2.sort_index()\n\ndf_merged = pd.concat([df1_sorted, df2_sorted], axis=1)\nprint(\"\\n排序后合并:\")\nprint(df_merged)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 场景4: 报表数据整理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建报表数据\nreport_data = pd.DataFrame({\n    'Q1': [1000, 1200, 800],\n    'Q3': [1100, 1300, 900],\n    'Q2': [1050, 1250, 850],\n    'Q4': [1200, 1400, 950]\n}, index=['产品A', '产品B', '产品C'])\n\nprint(\"原始报表数据:\")\nprint(report_data)\n\n# 按季度顺序排列列\ndf_sorted = report_data.sort_index(axis=1)\nprint(\"\\n按季度顺序排列:\")\nprint(df_sorted)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n\n### sort_index() vs sort_values() 对比\n\n| 特性 | sort_index() | sort_values() |\n|------|-------------|---------------|\n| 排序依据 | 索引标签 | 数据值 |\n| 主要用途 | 整理索引顺序 | 按值大小排序 |\n| 常用场景 | 时间序列、分组数据 | 排名、筛选 |\n| 多级支持 | 支持多级索引 | 支持多列排序 |\n\n### sort_index() 参数总结\n\n| 参数 | 默认值 | 说明 | 常用值 |\n|------|--------|------|--------|\n| `axis` | 0 | 排序轴 | 0(行索引), 1(列索引) |\n| `level` | None | 多级索引级别 | 数字或名称 |\n| `ascending` | True | 排序方向 | True(升序), False(降序) |\n| `inplace` | False | 是否修改原数据 | True, False |\n| `kind` | 'quicksort' | 排序算法 | 'quicksort', 'mergesort', 'heapsort' |\n| `na_position` | 'last' | 缺失值位置 | 'first', 'last' |\n| `key` | None | 自定义排序函数 | lambda 函数 |\n\n### 关键要点\n\n1. **行索引排序**: `df.sort_index()` (默认)\n2. **列索引排序**: `df.sort_index(axis=1)`\n3. **多级索引**: 使用 `level` 参数\n4. **时间序列**: 按时间顺序整理数据\n5. **数据合并**: 合并前先排序索引\n6. **自定义排序**: 使用 `key` 参数\n\n### 最佳实践\n\n```python\n# ✅ 推荐\ndf.sort_index()  # 简单索引排序\ndf.sort_index(axis=1)  # 列索引排序\ndf.sort_index(level=0)  # 多级索引排序\n\n# ❌ 注意\n# 确保索引类型一致，避免排序异常\n# 时间序列数据建议先排序再分析\n```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}